#include <libpub.h>

#define TEST_ALL_1      0xff
#define TEST_ALL_0      0x00
#define TEST_0_1        0x55
#define TEST_1_0        0xAA
#define TEST_55_AA      0x55AA
#define TEST_AA_55      0xAA55
#define TEST_55AA_55AA  0x55AA55AA
#define TEST_AA55_AA55  0xAA55AA55
#define SDRAM_START    0x80000000
#define SDRAM_END    0xc0000000

static int  mem_test_all_1(UINT32 addr, UINT32 len)
{
    register UINT32  i;
    for(i = 0; i < len; i++){
    *((char *)(addr + i)) = TEST_ALL_1;
    }
    for(i = 0; i < len; i++){
    if(*((char *)(addr + i)) != TEST_ALL_1)
        printf("\n0X%x: memory test ALL-1 error", (UINT32)(addr + i));
    }
    return 0;
}

static int  mem_test_all_0(UINT32 addr, UINT32 len)
{
    register UINT32  i;
    for(i = 0; i < len; i++){
    *((char *)(addr + i)) = TEST_ALL_0;
    }
    for(i = 0; i < len; i++){
    if(*((char *)(addr + i)) != TEST_ALL_0)
        printf("\n0X%x: memory test ALL-0 error", (UINT32)(addr + i));
    }
    return 0;
}

static int  mem_test_1_0(UINT32 addr, UINT32 len)
{
    register UINT32  i;
    for(i = 0; i < len; i++){
    *((char *)(addr + i)) = TEST_1_0;
    }
    for(i = 0; i < len; i++){
    if(*((char *)(addr + i)) != TEST_1_0)
        printf("\n0X%x: memory test 1-0 error", (UINT32)(addr + i));
    }
    return 0;
}

static int  mem_test_0_1(UINT32 addr, UINT32 len)
{
    register UINT32  i;
    for(i = 0; i < len; i++){
    *((char *)(addr + i)) = TEST_0_1;
    }
    for(i = 0; i < len; i++){
    if(*((char *)(addr + i)) != TEST_0_1)
        printf("\n0X%x: memory test 0-1 error",(UINT32)(addr + i));
    }
    return 0;
}

static int  mem_test_4_byte(UINT32 addr,UINT32 len)
{
    register UINT32  i,j;
    for(i = 0, j = 0; i < len /4; i++, j += 4){
    *((UINT32 *)(addr + j))  = TEST_55AA_55AA;
    }
    for(i = 0, j = 0; i < len /4; i++, j += 4){
    if(*((UINT32 *)(addr + j)) != TEST_55AA_55AA)
        printf("\n0X%x: memory test TEST_55AA_55AA error", (UINT32)(addr + j));
    }

    for(i = 0, j = 0; i < len /4; i++, j += 4){
    *((UINT32 *)(addr + j)) = TEST_AA55_AA55;
    }
    for(i = 0, j = 0; i < len /4; i++, j += 4){
    if(*((UINT32 *)(addr + j)) != TEST_AA55_AA55)
        printf("\n0X%x: memory test TEST_AA55_AA55 error",(UINT32)(addr + j));
    }

    return 0;
}

static int  mem_test_2_byte(UINT32 addr, UINT32 len)
{
    register UINT32 i, j;
    for(i = 0, j = 0; i < len /2; i++, j += 2){
    *((UINT16 *)(addr + j)) = TEST_55_AA;
    }
    for(i = 0, j = 0; i < len /2; i++, j += 2){
    if(*((UINT16 *)(addr + j)) != TEST_55_AA)
        printf("\n0X%x: memory test TEST_55_AA error",(UINT32)(addr + j));
    }

    for(i = 0, j = 0; i < len /2; i++, j += 2){
    *((UINT16 *)(addr + j)) = TEST_AA_55;
    }
    for(i = 0, j = 0; i < len /2; i++, j += 2){
    if(*((UINT16 *)(addr + j)) != TEST_AA_55)
        printf("\n0X%x: memory test TEST_AA_55 error",(UINT32)(addr + j));
    }

    return 0;
}

static int mem_test_1_byte(UINT32 addr, UINT32 length)
{
    mem_test_all_1(addr, length);
    mem_test_all_0(addr, length);
    mem_test_1_0(addr, length);
    mem_test_0_1(addr, length);
    return 0;
}

static inline int _Do_Test_Memory(UINT32 addr, UINT32 length)
{
    mem_test_1_byte(addr, length);
    mem_test_2_byte(addr, length);
    mem_test_4_byte(addr, length);
    return 0;
}

int Do_Test_Memory(char *param)
{
    UINT32 addr,   length;
    TOUT(1, 1, printf("Do_Test_Memory(\"%s\")\n", param));

    if (*param) {
        param = Bo_ParseInteger(param, (unsigned long *) &addr);
        if (*param) {// test memory addr length
            param = Bo_ParseInteger(param, (unsigned long *) &length);
            printf("\nNow Testing  0X%x--0X%x ... ...", addr, addr + length);
            _Do_Test_Memory(addr, length);
            printf("\nReport: total %d Bytes Memory Test OK!\n", length);
            return 0;
        }
    }
    else {
        //test memory  auto test 0x8000 0000-->0xc000 0000 here:
        addr = SDRAM_START;
        length = SDRAM_END - SDRAM_START;
        printf("\nNow Testing  0X%x--0X%x ... ...", addr, length);
        _Do_Test_Memory(addr, length);
        printf("\nReport: total %d Bytes Memory Test OK!\n", length);
        return 0;
    }
    printf("\n Error: param is null!\n");
    return -1;
}

